﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml;

using WebDavProcessor.Interfaces;
using WebDavProcessor.Resources;

namespace WCFServer.DataProviders
{
    class XmlFSDataAdapter : DataAdapter
    {
        string root;
        string storage;

        public XmlFSDataAdapter(string root, string physStorage)
        {
            this.root = root;
            storage = physStorage;
        }

        public override void WriteResource(ResourceInfo resource)
        {
            string physName = Path.Combine(storage, resource.ResourceName);
            FileStream fs = new FileStream(physName, FileMode.OpenOrCreate);
            XmlDocument doc = new XmlDocument();
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("<?xml version=\"1.0\"?>");
            sb.AppendLine(string.Format("<resource data=\"{0}\">", physName));
            foreach (string key in resource.Properties.Keys)
                sb.Append(string.Format("<{0}>{1}</{0}>", key, resource.Properties[key]));
            sb.AppendLine("</resource>");
            try
            {

                byte[] data = new byte[resource.Data.Length];
                resource.Data.Position = 0;
                resource.Data.Read(data, 0, data.Length);
                fs.Write(data, 0, data.Length);
                fs.Close();
                doc.LoadXml(sb.ToString());
                doc.Save(Path.Combine(root, resource.ResourceName));
            }
            catch (Exception)
            {
                try
                {
                    fs.Close();
                }
                catch
                {
                }
                throw;
            }
        }

        public override void DeleteResource(ResourceInfo resource)
        {
            try
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(Path.Combine(root, resource.ResourceName));
                string physPath = doc.SelectSingleNode("resource").Attributes["data"].Value;

                File.Delete(Path.Combine(root, resource.ResourceName));
                File.Delete(physPath);
            }
            catch (Exception)
            {
                throw;
            }
        }

        public override void RenameResource(string oldResourceName, string newResourceName)
        {
            throw new NotImplementedException();
        }

        public override bool IsExist(string resourcePath)
        {
            FileInfo fi = new FileInfo(Path.Combine(root, resourcePath));
            return fi.Exists;
        }

        public override ResourceInfo ReadResource(string resourcePath, int offset, int count)
        {
            try
            {
                ResourceInfo resource = ReadResourceLight(resourcePath);
                XmlDocument doc = new XmlDocument();
                doc.Load(Path.Combine(root, resource.ResourceName));
                string physPath = doc.SelectSingleNode("resource").Attributes["data"].Value;

                FileStream fs = File.OpenRead(physPath);
                byte[] data = new byte[fs.Length];
                if (count < 0)
                    count = data.Length;
                fs.Read(data, offset, count);
                fs.Close();

                MemoryStream ms = new MemoryStream(data);
                resource.Data = ms;
                return resource;
            }
            catch (Exception)
            {
                throw;
            }
        }

        public override ResourceInfo ReadResourceLight(string resourcePath)
        {
            try
            {
                ResourceInfo resource = new ResourceInfo(resourcePath);
                XmlDocument doc = new XmlDocument();
                doc.Load(Path.Combine(root, resource.ResourceName));
                XmlNode res = doc.SelectSingleNode("resource");

                foreach (XmlNode p in res.ChildNodes)
                {
                    resource.Properties.Add(p.Name, p.InnerText);
                }
                
                return resource;
            }
            catch (Exception)
            {
                throw;
            }
        }
    }

}
